#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#include <string.h>
#include <sys/types.h>
#include <unistd.h>
#include <errno.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <termios.h>
#include <pthread.h>
#include <arpa/inet.h>
#include <sstream>
#include <iostream>
#include <vector>
#include <string>
#include <iostream>

#include "../logServer/clogger.h"
#include "tdscdmaApi.h"
#include "tdscdmaMsgHandle.h"
#include "common.h"

#define TDSCDMALogDebug(fmt, args...) CLogger(MODULE_TDSCDMA_CAP, __FILE__, __LINE__, LOG_DEBUG, fmt, ##args);
#define TDSCDMALogInfo(fmt, args...) CLogger(MODULE_TDSCDMA_CAP, __FILE__, __LINE__, LOG_INFO, fmt, ##args);
#define TDSCDMALogNotice(fmt, args...) CLogger(MODULE_TDSCDMA_CAP, __FILE__, __LINE__, LOG_NOTICE, fmt, ##args);
#define TDSCDMALogWarning(fmt, args...) CLogger(MODULE_TDSCDMA_CAP, __FILE__, __LINE__, LOG_WARNING, fmt, ##args);
#define TDSCDMALogError(fmt, args...) CLogger(MODULE_TDSCDMA_CAP, __FILE__, __LINE__, LOG_ERR, fmt, ##args);
#define TDSCDMALogCrit(fmt, args...) CLogger(MODULE_TDSCDMA_CAP, __FILE__, __LINE__, LOG_CRIT, fmt, ##args);
#define TDSCDMALogAlert(fmt, args...) CLogger(MODULE_TDSCDMA_CAP, __FILE__, __LINE__, LOG_ALERT, fmt, ##args);
#define TDSCDMALogEmerg(fmt, args...) CLogger(MODULE_TDSCDMA_CAP, __FILE__, __LINE__, LOG_EMERG, fmt, ##args);

#define TDSCDMA_DEBUG  1
#define TDSCDMA_SLOT   12

using namespace std;

//communication address
sockaddr_in 	   remoteAddr;
sockaddr_in 	   localAddr;
conn_context       tdscdma_udp_ctxt;
conn_t*            tdscdma_udp_conn_t = NULL;

//tdscdma module state
const char *tdscdmaStatesStr[(int)TDSCDMA_MODULE_NSYNC+1] =
{
    "Idle",
    "PreConfig",
    "Configuring",
    "Configured",
    "Restarting",
    "Running",
    "Shutdown",
    "OOS"
};

#define TDSCDMA_GET_MSG_SET_NUM   4
I32   TDSCDMA_GET_MSG_SET[TDSCDMA_GET_MSG_SET_NUM] =
{
	MSG_GET_VERSION,
	MSG_GET_SCAN_CELL,
	MSG_GET_RF_SWITCH,
	MSG_GET_SYNC    
};

#define BACKED_MSG_NUMBER      5
#define BACKED_MAX_LENGTH      2048

typedef struct backedMsgTag
{
    U8							msg[BACKED_MAX_LENGTH];
    U16                         len;
	U32                         sessionId;
}backedMsg;

//some runtime information
tdscdmaParam_t         gTdscdmaParam;                        /* global tdscdma configuration */
tdscdmaGloadContext    tdscdmaContext;                       /*                */
tdscdmaModuleState_t   gTdscdmaState;                        /* global tdscdma module state */
tlvCmdRecord_t         tdscdmaCmdRecord[2];	                 /* save destination module ID and cmd code */
time_t				   tdscdmaCurTime;		                 /* current time counter since from 1970 */
backedMsg       	   tdscdmaBackedMsg[BACKED_MSG_NUMBER];	 /* the lastest udp message */
U32                    tdscdmaSendcout[RC_MOD_INVALID];      /* send ok */   
U16 				   tdscdmaHbCounter;		             /* count how many heart beat message received */
U16                    tdscdmaResetCount;                   /*count reboot tdscdma */
bool                   tdscdamIsSetTime = true;              /* set tdscdma board time at the first time */
pthread_mutex_t        tdscdmaMutex;                         /* for modify cdma baseband state between two thread */
U32                    globalSession;                        /* record the latest session can be used */
MODREG modTdscdmaInfo = {MODULE_TDSCDMA_CAP, true, true, TICK_INTERVAL, (char *)"TDSCDMA"};

#define TDSCDMA_HAERTBEAT_INTERVAL       5000
#define TDSCDMA_RESTART_CMD_INTERVAL     5000

#define TDSCDMA_MODULE_HEARTBEAT_INTERVAL  5000
#define TDSCDMA_BOARD_HEARTBEAT_INTERVAL   15 * 60 * 1000
const U32 checktdscdmaImsiInterval = 120 * 60 * 1000; //2 hours
void* pTdscdmaModuleHeartBeatTimer = NULL;
void* pTdscdmaRestartCommandTimer = NULL;
void* pTdscdmaBoardHeartBeatTimer = NULL;
void* pTdscdmaRecvImsiTimer = NULL;
static bool tdscdmaHavedRecvImsi = false;
//module init function
bool tdscdmaModuleInit();
void tdscdma_tlv_msg_handler();
bool initTdscdmaInternalMsgTask();
bool initTdscdmaUdpMsgTask();

const char hardInitConfig[] =
{
 0x00,0x00,0x00,0x05,0x00,0x01,0x00,0x00,0xdc,0x00,0x00,0x02,0x00,0x00,0x03,0x00
,0x31,0x39,0x32,0x2e,0x31,0x36,0x38,0x2e,0x31,0x37,0x38,0x2e,0x31,0x31,0x31,0x00
,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
,0x00,0x00,0x17,0xac,0x00,0x00,0x17,0xac,0x27,0x47,0x00,0x40,0x00,0x13,0x00,0x00
,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x04,0x06,0x00,0x00,0x00,0x02,0x00,0x00
,0x00,0x00,0x00,0x00,0x04,0x06,0x00,0x00,0x00,0x02,0x00,0x00,0x00,0x02,0x00,0x00
,0x00,0x02,0x00,0x05,0x00,0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00    
};

/*************************************************************************/
/*     handle PA control */
/**********************************************************************/
static bool tdscdmaPaIsOn = false;
static bool tdscdmaPaSettingOn = false;
static int tdscdmaMaxPaCtrlTm = 3;
static U8 tdscdmaPaHandleType = 0;


#define TDSCDMA_PA_TYPE_REBOOT          1
#define TDSCDMA_PA_TYPE_NOTHING         0
#define TDSCDMA_PA_TYPE_RESTART         2

const U32 contrlTdscdmaPaTimeOut = 30* 1000;
void* pTdscdmaCtrlPaTimer = NULL;
void handleTdscdmaCtrlPaTimer(void *h);
void handleTdscdmaPaCtrl(bool settingOn, U8 type);


/*
 *******************************************************************************
 *            common function definition
 *
 ******************************************************************************* 
 */
/* 
 ******************************************************************************* 
 * @brief   Get self module ID
 * @return  Self Module ID 
 *
 ******************************************************************************* 
 */ 
PCMDHEADER getTdscdmaTlvCmdHeader(U16 cmdType);
U16 getTdscdmaTlvSrcID(U16 cmdType);
void saveTdscdmaMsgCmdCodeAndSrcID(U16 srcID, PCMDHEADER);
void setTdscdmadevtimestr(char * str);
void tdscdmaBackupLatestUdpMsg(const char *msg, U16 msglen, U32 sessionId);
void resendingTdscdmaBackupUdpMsg(U32 sessionId);
tdscdmaModuleState_t getTdscdmaModuleState();
void setTdscdmaModuleState(tdscdmaModuleState_t state);
bool init_tdscdma_udp_context(sockaddr_in *remote_addr, sockaddr_in* local_addr);
void send_common_tdscdma_msg(U32 msgId, U32 sessionId);
void send_tdscdma_udp_msg(const char *msg, U16 length, U32 sessionId);
void setTdscdmaModuleRecvImsi();
bool getTdscdmaModuleRecvImsi();
/*
 *******************************************************************************
 *            tlv relate function
 *
 ******************************************************************************* 
 */
 
/**
 ****************************************************************************************
 * @brief   build and send alarm to dispatcher module, 
 * @param   result            -  failed or success
 * @return  true or false
 ****************************************************************************************
 */
bool buildAndSendTdscdmaTlvCmdSetResponseMsg(U8 cmdType, U32 result, U32 paraType, U32 paraValue);

/**
 ****************************************************************************************
 * @brief   build and send alarm to dispatcher module, 
 * @return  none
 ****************************************************************************************
 */
void tdscdmaBuildAndSendTlvEventNoParam(U16 moduleID, U16 cmdCode);

/**
 ****************************************************************************************
 * @brief   build and send alarm to dispatcher module, 
 * @param   paramType         -  udp connection context
 * @param   paramValue        -  udp connection
 * @return  none
 ****************************************************************************************
 */ 
void tdscdmaBuildAndSendTlvEvent(U16 moduleID, U16 cmdCode, U32 paramType, U32 paramValue);

/**
 ****************************************************************************************
 * @brief   build and report tdscdma module status
 * @return  none
 ****************************************************************************************
 */
void handleTdscdmaTlvTimeTick();
void handleTdscdmaTlvCmdMsg(U8 *payload);
void handleTdscdmaTlvCmdSetMsg(U8 *payload);
void handleTdscdmaTlvCmdSetRspMsg(void *payload);
void handleTdscdmaGetTdscdmaConfiguration(PCMDHEADER pCmd);
void handleTdscdmaTlvCmdGetMsg(U8 *payload);
void handleTdscdmaTlvCmdEventMsg(U8 *payload);
void handleTdscdmaTlvCtrlRestartMsg();
void handleTdscdmaTlvCtrlWirelessSwitch(U32 rfSwitch);
void handleTdscdmaTlvCtrlSniffer(PCMDHEADER pCmd);
void handleTdscdmaTlvSetTxAttuation(PCMDHEADER pCmd);
void handleTdscdmaTlvConfigWirelessMsg(PCMDHEADER pCmd);
void buildAndReportTdscdmaModuleStatus();
void reportHeartBeatTdscdmaModuleStatus();
void handleTdscdmaRecvImsiTimer(void *h);
/**
 ****************************************************************************************
 * @brief   build and report tdscdma configuration 
 * @return  none
 ****************************************************************************************
 */
void handleTdscdmaMsgInit(const char* buf, ssize_t len);
void handleTdscdmaMsgHeartBeat(const char* buf, ssize_t len);
void handleTdscdmaMsgInitConfigAck(const char* buf, ssize_t len);
void handleTdscdmaMsgRemCellInd(const char* buf, ssize_t len);			
void handleTdscdmaMsgScanCellInd(const char* buf, ssize_t len);
void handleTdscdmaMsgGetSyncAck(const char* buf, ssize_t len);	 
void handleTdscdmaMsgSetCellAck(const char* buf, ssize_t len);
void handleTdscdmaMsgSetScanCellAck(const char* buf, ssize_t len); 		
void handleTdscdmaMsgGetScanCellAck(const char* buf, ssize_t len); 
void handleTdscdmaMsgGetRfSwitchAck(const char* buf, ssize_t len);		   
void handleTdscdmaMsgGetVersionAck(const char* buf, ssize_t len);			 
void handleTdscdmaMsgRebootAck(const char* buf, ssize_t len);
void handleTdscdmaMsgUeReport(const char* buf, ssize_t len);
void handleMsgALarmInd(const char* buf, ssize_t len);
void handleTdscdmaMsgHeartBeatAck(const char* buf, ssize_t len);



//message send operation
void sendTdscdmaInitAck(U32 sessionId);
void sendTdscdmaInitConfig(U32 sessionId);
void sendTdscdmaConfigCell(U32 sessionId);
void sendTdscdmaReboot(U32 rebootType);
void sendTdscdmaHeartbeat();


/*
 *******************************************************************************
 *            common function definition
 *
 ******************************************************************************* 
 */
void handleTdscdmaModuleHeartBeatTimer(void *h);
void handleTdscdmaBoardHeartBeatTimer(void *h);

inline time_t getTdscdmaCurrentTime()
{
    return tdscdmaCurTime;
}

inline void setTdscdmaCurrentTime()
{
    tdscdmaCurTime = time(NULL);
}

inline void increaseTdscdmaCurrentTime(int tick)
{
    tdscdmaCurTime += tick;
}

inline void increaseSendCounter(RESULT rc)
{
    tdscdmaSendcout[rc]++;
}

U16 getTdscdmaTlvSrcID(U16 cmdType)
{
     return tdscdmaCmdRecord[cmdType].srcID;
}

PCMDHEADER getTdscdmaTlvCmdHeader(U16 cmdType)
{
    return &(tdscdmaCmdRecord[cmdType].cmdHdr);
}

void saveTdscdmaMsgCmdCodeAndSrcID(U16 srcID, PCMDHEADER hdr)
{
     tdscdmaCmdRecord[hdr->cmdType].srcID = srcID;
     tdscdmaCmdRecord[hdr->cmdType].cmdHdr.cmdIndex = hdr->cmdIndex;
     tdscdmaCmdRecord[hdr->cmdType].cmdHdr.cmdCode = hdr->cmdCode;
     tdscdmaCmdRecord[hdr->cmdType].cmdHdr.cmdType = hdr->cmdType;

     TDSCDMALogDebug("modId[0x%x] cmdcode = %02x, srcId = %02x ", MODULE_TDSCDMA_CAP, hdr->cmdCode, srcID);
}

MsgRemCellInd *getRemCellInd()
{
    return &(tdscdmaContext.remCellInd);
}

tdscdmaParam_t *getTdscdmaParam()
{
    return &(tdscdmaContext.param);
}

void setDefaultMsgHeader(GeneralHeader *msg)
{
	msg->mjVer = MSG_TDSCDMA_MJVER;
	msg->mnVer = MSG_TDSCDMA_MNVER;
	msg->messageId = 0;	
	msg->length = 0;
}

static void closeTdscdmaSession(void)
{    
	TDSCDMALogNotice("System is exiting, closing tdscdma socket.");
	release_connection(tdscdma_udp_conn_t);
}

/**
**************************************************************************
* handle PA
*
*****************************************************************************/
void buildAndSendTdscdmaPaCtrlCommand(bool isOn)
{
    U8 slotId = 11;
    if (isOn)
    {
        CM_SendMsg_1Para(MODULE_PA, MODULE_TDSCDMA_CAP, MSG_TYPE_COMMAND, CMD_SET, CMD_CODE_PA_SWITCH_ON, 0,
                PARA_TYPE_PA_ADDR, sizeof(U8), &slotId);
    }
    else
    {
        CM_SendMsg_1Para(MODULE_PA, MODULE_TDSCDMA_CAP, MSG_TYPE_COMMAND, CMD_SET, CMD_CODE_PA_SWITCH_OFF, 0,
                PARA_TYPE_PA_ADDR, sizeof(U8), &slotId);		
    }
}

void handleTdscdmaCtrlPaTimer(void *h)
{
    if (tdscdmaMaxPaCtrlTm <= 0)
    {

        TDSCDMALogWarning("tdscdma pa control max time reach ");
        if (tdscdmaPaHandleType == TDSCDMA_PA_TYPE_NOTHING)
        {
            TDSCDMALogNotice("tdscdma pa contorl failed  do nothing");
        }
        else if (tdscdmaPaHandleType == TDSCDMA_PA_TYPE_REBOOT)
        {
            TDSCDMALogNotice("tdscdma pa contorl failed reboot");
            handleTdscdmaTlvCtrlRestartMsg();
        }
        else if (tdscdmaPaHandleType == TDSCDMA_PA_TYPE_RESTART)
        {
            TDSCDMALogNotice("tdscdma pa contorl failed restart");
            U8 slotId = 12;
            CM_SendMsg_1Para(MODULE_PM, MODULE_TDSCDMA_CAP, MSG_TYPE_COMMAND, CMD_SET, CMD_CODE_PM_RESTART, 0,
                    PARA_TYPE_PM_GPIO_CTRL_PIN, sizeof(U8), &slotId);
            tdscdmaResetCount++;
        }

        return;

    }
    tdscdmaMaxPaCtrlTm--;
    if (tdscdmaPaIsOn == tdscdmaPaSettingOn)
    {
        TDSCDMALogNotice("tdscdma pa state is same  do nothing");
        return;
    }

    buildAndSendTdscdmaPaCtrlCommand(tdscdmaPaSettingOn);
    MOD_timerRestart(pTdscdmaCtrlPaTimer, contrlTdscdmaPaTimeOut);
}


void handleTdscdmaCtrlPaResult(bool isOn)
{
    if (!isOn && tdscdmaPaSettingOn)
    {
        TDSCDMALogWarning("tdscdma pa handle type is chang so do default command");
        handleTdscdmaTlvCtrlRestartMsg();
    }


    if (isOn == tdscdmaPaSettingOn)
    {
        tdscdmaPaIsOn = isOn;
        TDSCDMALogWarning("tdscdma pa control  success");
        if (tdscdmaPaHandleType == TDSCDMA_PA_TYPE_NOTHING)
        {
            TDSCDMALogNotice("tdscdma pa control	success  do nothing");
        }
        else if (tdscdmaPaHandleType == TDSCDMA_PA_TYPE_REBOOT)
        {
            TDSCDMALogNotice("tdscdma pa control	success reboot");
            handleTdscdmaTlvCtrlRestartMsg();
        }
        else if (tdscdmaPaHandleType == TDSCDMA_PA_TYPE_RESTART)
        {
            TDSCDMALogNotice("tdscdma pa control	success so restart");
            U8 slotId = 12;
            CM_SendMsg_1Para(MODULE_PM, MODULE_TDSCDMA_CAP, MSG_TYPE_COMMAND, CMD_SET, CMD_CODE_PM_RESTART, 0,
                    PARA_TYPE_PM_GPIO_CTRL_PIN, sizeof(U8), &slotId);
            tdscdmaResetCount++;

        }
        ///MOD_timerClear(MODULE_GSM_CAP, pGsmCtrlPaTimer);
    }
    else
    {
        TDSCDMALogWarning("tdscdma pa handle type is chang");
    }	

}
void handleTdscdmaPaCtrl(bool settingOn, U8 type)
{
    tdscdmaPaHandleType = type;
    if ((tdscdmaPaIsOn == settingOn) && (tdscdmaPaSettingOn == settingOn))
    {
        if (tdscdmaPaHandleType == TDSCDMA_PA_TYPE_NOTHING)
        {
            TDSCDMALogNotice("tdscdma pa state is same  do nothing");
        }
        else if (tdscdmaPaHandleType == TDSCDMA_PA_TYPE_REBOOT)
        {
            TDSCDMALogNotice("tdscdma pa state is same reboot");
            handleTdscdmaTlvCtrlRestartMsg();
        }
        else if (tdscdmaPaHandleType == TDSCDMA_PA_TYPE_RESTART)
        {
            TDSCDMALogNotice("tdscdma pa state is same restart");

            TDSCDMALogWarning("reboot tdscdma baseband time is %d ",	tdscdmaResetCount);
            U8 slotId = 12;
            CM_SendMsg_1Para(MODULE_PM, MODULE_TDSCDMA_CAP, MSG_TYPE_COMMAND, CMD_SET, CMD_CODE_PM_RESTART, 0,
                    PARA_TYPE_PM_GPIO_CTRL_PIN, sizeof(U8), &slotId);
            tdscdmaResetCount++;
        }

        return;
    }

    tdscdmaMaxPaCtrlTm = 2;
    tdscdmaPaSettingOn = settingOn;
    buildAndSendTdscdmaPaCtrlCommand(tdscdmaPaSettingOn);
    if (pTdscdmaCtrlPaTimer == NULL)
    {
        pTdscdmaCtrlPaTimer = MOD_timerStart(MODULE_TDSCDMA_CAP, contrlTdscdmaPaTimeOut, handleTdscdmaCtrlPaTimer, NULL);
    }
    else
    {

        MOD_timerRestart(pTdscdmaCtrlPaTimer, contrlTdscdmaPaTimeOut);
    }


}


/************************************************/
/* pa											*/
/************************************************/
void handleTdscdmaPAOnReponse(PCMDHEADER pCmd)
{
    PPARAM pParam =(PPARAM)(pCmd+1);

    U32 len = pCmd->cmdLength;
    U32 paraType;
    U32 paraLength;
    U8* paraValue;
    UNPACK_RESULT uprc; 
    U32  result = PARA_VALUE_ERROR_GENERAL_ERROR;

    while((uprc=CM_paraUnpackPara(&pParam, &len, &paraType, &paraLength,&paraValue)) == UNPACK_OK)	  
    {
        switch(paraType)
        {
            case PARA_TYPE_RESULT:
                result = *((U32 *) paraValue);

                break;

            case PARA_TYPE_PA_ADDR:

                break;
            default:
                TDSCDMALogError("Unknown paramType error in received cmdcode = %x", pCmd->cmdCode);


                break;
        }

    }

    if( uprc == UNPACK_ERROR )
    {
        TDSCDMALogError("tdscdma pa reponse un pack failed");
        return;
    }

    if (result == PARA_VALUE_ERROR_NO_ERROR)
    {
        handleTdscdmaCtrlPaResult(true);

    }

}

void handleTdscdmaPAOffReponse(PCMDHEADER pCmd)
{
    PPARAM pParam =(PPARAM)(pCmd+1);

    U32 len = pCmd->cmdLength;
    U32 paraType;
    U32 paraLength;
    U8* paraValue;
    UNPACK_RESULT uprc; 
    U32  result = PARA_VALUE_ERROR_GENERAL_ERROR;

    while((uprc=CM_paraUnpackPara(&pParam, &len, &paraType, &paraLength,&paraValue)) == UNPACK_OK)	  
    {
        switch(paraType)
        {
            case PARA_TYPE_RESULT:
                result = *((U32 *) paraValue);

                break;

            case PARA_TYPE_PA_ADDR:

                break;
            default:
                TDSCDMALogError("Unknown paramType error in received cmdcode = %x", pCmd->cmdCode);


                break;
        }

    }

    if( uprc == UNPACK_ERROR )
    {
        TDSCDMALogError("tdscdma pa reponse un pack failed");
        return;
    }

    if (result == PARA_VALUE_ERROR_NO_ERROR)
    {
        handleTdscdmaCtrlPaResult(false);

    }

}


void handleTdscdmaTlvCmdSetRspMsg(U8 *payload)
{
    PCMDHEADER pCmd  = (PCMDHEADER ) payload;

    switch (pCmd->cmdCode)
    {	
        case CMD_CODE_PA_SWITCH_ON:
            handleTdscdmaPAOnReponse(pCmd);
            break;
        case CMD_CODE_PA_SWITCH_OFF:
            handleTdscdmaPAOffReponse(pCmd);
            break;

        default:
            TDSCDMALogWarning("Unknown cmdCode = %x ",  pCmd->cmdCode);
            break;
    }	
}

/**
 ****************************************************************************************
 * Set devtimestr, time is string 
 *   
 ****************************************************************************************
 */ 
void setTdscdmadevtimestr(char *str)
{
    time_t   now;
    struct   tm  *timenow;

    /* 1. get system time */
    now = getTdscdmaCurrentTime();
    timenow = localtime(&now);
    char s[15];
    strftime(s, sizeof(s), "%Y%m%d%H%M%S", timenow);
    TDSCDMALogDebug( "time:%s", s);
    memcpy(str, s, sizeof(s));
    TDSCDMALogDebug( "DEVTIMESTR:%s",str);
}

void tdscdma_tlv_msg_handler()
{
    MSGHEADER msgHdr;
    U8 payload[MAX_MSG_SIZE];
    PCMDHEADER pCmd;
	  
    while(1)
    {
        if( MSG_read(MODULE_TDSCDMA_CAP, &msgHdr, (void *)payload) != 0 )
        {
            //dbgprintf(DEBUG_ERROR, stderr, "internal_msg_thread:MSG_read error. \n");
            continue;
        }
    
        if( MODULE_TDSCDMA_CAP != msgHdr.dstID )
        {
            TDSCDMALogError("received a wrong tlv msg id = %d ", msgHdr.dstID);
            continue;
        }

        switch ( msgHdr.msgType )
        {
            case MSG_TYPE_COMMAND:
            	pCmd = (PCMDHEADER )payload;
            	
            	//save cmdcode and srcId for response
                if (pCmd->cmdType == CMD_SET || pCmd->cmdType == CMD_GET)
            	    saveTdscdmaMsgCmdCodeAndSrcID(msgHdr.srcID, pCmd);            	
            	handleTdscdmaTlvCmdMsg(payload);
            	break;
            case MSG_TYPE_TICK:
            	handleTdscdmaTlvTimeTick();
            	break;
            default:
              TDSCDMALogError("Unknown msg type %x.", msgHdr.msgType);
              break;
        }
    }
}

bool tdscdmaModuleInit()
{
    //1. init global parameter
    memset(&gTdscdmaParam, 0x0, sizeof(tdscdmaParam_t));
    memset(&tdscdmaCmdRecord, 0x0, sizeof(tlvCmdRecord_t) * 2);
    memset(tdscdmaBackedMsg, 0x0, sizeof(backedMsg) * BACKED_MSG_NUMBER);
	globalSession = 0;
	gTdscdmaState = TDSCDMA_MODULE_IDLE;
	tdscdmaHbCounter = 0;
    tdscdmaResetCount = 0;
    //2. register module
    if( RC_OK != MOD_register(&modTdscdmaInfo) )
    {
        dbgprintf(DEBUG_ERROR, stderr, "modId[0x%x] can't register tdscdma module with syscore\n", MODULE_TDSCDMA_CAP);
        return false;
    }

    //3. init udp context
    remoteAddr.sin_addr.s_addr = inet_addr(TDSCDMA_BOARD_IP);
	remoteAddr.sin_port = htons(atoi(TDSCDMA_BOARD_UDP_PORT));
	remoteAddr.sin_family = AF_INET;
    localAddr.sin_addr.s_addr = inet_addr(TDSCDMA_MODULE_IP);
	localAddr.sin_port = htons(atoi(TDSCDMA_MODULE_UDP_PORT));
	localAddr.sin_family = AF_INET;
    if(!init_tdscdma_udp_context(&remoteAddr, &localAddr) )
    {
        TDSCDMALogError("init udp connection context.");
        return false;
    }

    //set system time
    setTdscdmaCurrentTime();

    return true;
}

//
RESULT TDSCDMA_init(void)
{
    //1. tdscdma module initialization
    if( !tdscdmaModuleInit() )
    {	
        TDSCDMALogError("TDSCDMA module initialization failed. \n", MODULE_TDSCDMA_CAP);
    	return RC_FAIL; 
    }
    
    //2. create udp msg handler thread 
    if( !initTdscdmaUdpMsgTask() )
    {
        TDSCDMALogError("Can't create tdscdmaUdpMsgTask thread. \n", MODULE_TDSCDMA_CAP);
    	return RC_FAIL;
    }

    //3. create internal msg handler thread 
    if( !initTdscdmaInternalMsgTask() )
    {
        TDSCDMALogError("Can't create tdscdmaInternalMsgtask thread. \n", MODULE_TDSCDMA_CAP);
    	return RC_FAIL;
    }

    return RC_OK;
}

static void* tdscdma_internal_task_thread(void *arg __attribute__((unused)))
{
    pthread_setname_np(pthread_self(), "tdscdma_internal");
    pTdscdmaModuleHeartBeatTimer = MOD_timerStart(MODULE_TDSCDMA_CAP, TDSCDMA_MODULE_HEARTBEAT_INTERVAL, handleTdscdmaModuleHeartBeatTimer, NULL);
    pTdscdmaBoardHeartBeatTimer = MOD_timerStart(MODULE_TDSCDMA_CAP, TDSCDMA_BOARD_HEARTBEAT_INTERVAL, handleTdscdmaBoardHeartBeatTimer, NULL);
    pTdscdmaRecvImsiTimer = MOD_timerStart(MODULE_TDSCDMA_CAP, checktdscdmaImsiInterval, handleTdscdmaRecvImsiTimer, NULL);
	atexit(closeTdscdmaSession);

	//start to handle message from other module
    tdscdma_tlv_msg_handler();

    TDSCDMALogNotice("Exiting the tdscdma_internal_task_thread thread\n", MODULE_TDSCDMA_CAP);
    pthread_exit( (void*)0 );
}

bool initTdscdmaInternalMsgTask()
{
    pthread_t       thread;

    if(pthread_create(&thread, NULL, tdscdma_internal_task_thread, NULL) != RC_OK)
    {
        return false;
    }

    return true;
}

/****************************************************************************************/
/*           tlv relate function                                                        */
/****************************************************************************************/
/****************************************************************************************/
/*           Handle time tick from dispatcher module                                    */
/****************************************************************************************/
void handleTdscdmaTlvTimeTick()
{
    increaseTdscdmaCurrentTime(TICK_SECOND);
    MOD_timerProc(MODULE_TDSCDMA_CAP);
	if((tdscdmaCurTime % 60) == 0) 
	{
        sendTdscdmaHeartbeat();
	}    
} 

void handleTdscdmaModuleHeartBeatTimer(void *h)
{
    U32 rc = PARA_VALUE_SYSMONITOR_MODULE_OK;
    CM_SendMsg_1Para(MODULE_SYSMONITOR, MODULE_TDSCDMA_CAP, MSG_TYPE_COMMAND, CMD_EVENT, CMD_CODE_SYSMONITOR_HEARTBEAT, 0,
        PARA_TYPE_SYSMONITOR_MODULE_STATE,sizeof(U32), (U8*)&rc);   
     
    MOD_timerRestart(pTdscdmaModuleHeartBeatTimer, TDSCDMA_MODULE_HEARTBEAT_INTERVAL);
}

void handleTdscdmaBoardHeartBeatTimer(void *h)
{
    MOD_timerRestart(pTdscdmaBoardHeartBeatTimer, TDSCDMA_BOARD_HEARTBEAT_INTERVAL);
    
    if(TDSCDMA_MODULE_IDLE == getTdscdmaModuleState() ||
       TDSCDMA_MODULE_RESTART == getTdscdmaModuleState() ||
       TDSCDMA_MODULE_PRECONFIG == getTdscdmaModuleState())
    {
        return;
    }

    if (TDSCDMA_MODULE_NSYNC == getTdscdmaModuleState() && tdscdmaResetCount >= 3)
    {
        TDSCDMALogNotice("tdscdma reset time is %d", tdscdmaResetCount);
        if (tdscdmaResetCount == 3)
        {
            tdscdmaResetCount++;
            tdscdmaBuildAndSendTlvEventNoParam(MODULE_INTF, CMD_TDSCDMA_EVT_LOST);
            saveImportantLog((char *)"tdscdma baseband lost connction, hard reset no use");
        }
        return;
    }
    //tdscdma board is sync with x86
    if (tdscdmaHbCounter > 0)
    {
        tdscdmaHbCounter = 0;
        tdscdmaResetCount = 0;
    }
    else
    {
        //if tdscdma board is out of sync, whether need trigger an alert and reboot?	  	  	  
        setTdscdmaModuleState(TDSCDMA_MODULE_NSYNC);
        TDSCDMALogWarning("TDSCDMA lost heartbeat");       
        //sent to power module to restart wcdma board
		//handleTlvCtrlResetMsg(0);
        tdscdmaBuildAndSendTlvEventNoParam(MODULE_INTF, CMD_TDSCDMA_EVT_NSYNC);
		handleTdscdmaPaCtrl(false, TDSCDMA_PA_TYPE_RESTART);

    }
}
  
void handleTdscdmaRecvImsiTimer(void *h)
{
    MOD_timerRestart(pTdscdmaRecvImsiTimer, checktdscdmaImsiInterval);
    
    if(TDSCDMA_MODULE_IDLE == getTdscdmaModuleState() ||
       TDSCDMA_MODULE_RESTART == getTdscdmaModuleState() ||
       TDSCDMA_MODULE_NSYNC == getTdscdmaModuleState() ||
       TDSCDMA_MODULE_PRECONFIG == getTdscdmaModuleState())
    {
        return;
    }

    if (!getTdscdmaModuleRecvImsi())
    {
        tdscdmaBuildAndSendTlvEventNoParam(MODULE_INTF, CMD_TDSCDMA_EVT_NOT_RECV_IMSI);  
        if (tdscdmaResetCount <= 3)
        {
            handleTdscdmaPaCtrl(false, TDSCDMA_PA_TYPE_REBOOT);
        }
        TDSCDMALogWarning("tdscdma module can not recv imsi in two hour");    
        return;  
    }
    TDSCDMALogInfo("tdscdma module have recv imsi in two hour");   

}

void handleTdscdmaTlvCmdMsg(U8 *payload)
{
    PCMDHEADER pCmd = (PCMDHEADER) payload;

    switch (pCmd->cmdType)
    {
        case CMD_SET:
       	    handleTdscdmaTlvCmdSetMsg(payload);
            break;
        case CMD_GET:
            handleTdscdmaTlvCmdGetMsg(payload);
            break;
        case CMD_EVENT:
            handleTdscdmaTlvCmdEventMsg(payload);
            break;
        default:
            TDSCDMALogWarning("Unknown CmdType = %x",  pCmd->cmdType);
            break;
    }
}

void handleTdscdmaTlvCmdSetMsg(U8 *payload)
{
    PCMDHEADER pCmd  = (PCMDHEADER ) payload;
	 
    switch (pCmd->cmdCode)
    {
        case CMD_TDSCDMA_RESTART:
            handleTdscdmaPaCtrl(false, TDSCDMA_PA_TYPE_REBOOT);
            break;
        case CMD_TDSCDMA_WIRELESS_OFF:
            handleTdscdmaTlvCtrlWirelessSwitch(0);
            break;
        case CMD_TDSCDMA_WIRELESS_ON:
            handleTdscdmaTlvCtrlWirelessSwitch(1);
            break;    	
		case CMD_TDSCDMA_DO_SNIFFER:
			handleTdscdmaTlvCtrlSniffer(pCmd);
			break;
        case CMD_TDSCDMA_CFG_WIRELESS:
            handleTdscdmaTlvConfigWirelessMsg(pCmd);
            break;
        case CMD_TDSCDMA_TX_ATTUATION:
            handleTdscdmaTlvSetTxAttuation(pCmd);
            break;
        default:
            TDSCDMALogWarning("Unknown cmdCode = %x \n", pCmd->cmdCode);
            break;
    }
}

void handleGetTdscdmaConfiguration(PCMDHEADER pCmd)
{

}

void handleGetTdscdmaModuleInfo(PCMDHEADER pCmd)
{
    PPARAM pParam =(PPARAM)(pCmd+1);
    U32 len = pCmd->cmdLength;
    U32 paraType;
    U32 paraLength;
    U8* paraValue;
    UNPACK_RESULT uprc; 

    GeneralHeader  msg;
	setDefaultMsgHeader(&msg);
	
    while((uprc=CM_paraUnpackPara(&pParam, &len, &paraType, &paraLength,&paraValue)) == UNPACK_OK)
    {
        switch(paraType)
        {
            case PARA_TYPE_TDSCDMA_WILELESS_STATE:
				msg.messageId = MSG_GET_RF_SWITCH;
                break;
            case PARA_TYPE_TDSCDMA_SOFTWARE_VERSION:
				msg.messageId = MSG_GET_VERSION;
                break;	
            case PARA_TYPE_TDSCDMA_SYNC_STATUS:
				msg.messageId = MSG_GET_SYNC;
                break;	
            default:
                TDSCDMALogError("Unknown paramType error in received cmdcode = %x",   pCmd->cmdCode);
                buildAndSendTdscdmaTlvCmdSetResponseMsg(CMD_SET, PARA_VALUE_RESULT_FAILED, PARA_TYPE_ERROR_CODE, PARA_VALUE_ERROR_UNKNOWN_PARATYPE);
                break;
        }
    }

    if( uprc == UNPACK_ERROR )
    {
        TDSCDMALogError("Parameter unpack error in received cmdcode = %x", pCmd->cmdCode);

        buildAndSendTdscdmaTlvCmdSetResponseMsg(CMD_SET, PARA_VALUE_RESULT_FAILED, PARA_TYPE_ERROR_CODE, PARA_VALUE_ERROR_ILLEGAL_PARA_STRUCT);
        
        return;
    }

	//msg.sessionId = htonl(globalSession++);
	//send_tdscdma_udp_msg((char *)&msg, sizeof(GeneralHeader), msg.messageId);
}

void handleTdscdmaTlvCmdGetMsg(U8 *payload)
{
    PCMDHEADER pCmd  = (PCMDHEADER ) payload;

    switch (pCmd->cmdCode)
    {  	
        case CMD_TDSCDMA_GET_MODULE_STATUS:
            buildAndReportTdscdmaModuleStatus();
            break;
        case CMD_TDSCDMA_GET_MODULE_CFG:
			handleGetTdscdmaConfiguration(pCmd);
            break; 
        case CMD_TDSCDMA_GET_MODULE_INFO:
            handleGetTdscdmaModuleInfo(pCmd);
            break;
        default:
          TDSCDMALogWarning("Unknown cmdCode = %x \n",  pCmd->cmdCode);
          break;
    }		
}

void handleTdscdmaTlvCmdEventMsg(U8 *payload)
{
    PCMDHEADER pCmd  = (PCMDHEADER ) payload;

    switch (pCmd->cmdCode)
    {  	
        case CMD_CODE_SYS_TIME_SYNC:
            setTdscdmaCurrentTime();
            break;
        case CMD_CODE_SYS_WAKE:
            handleTdscdmaTlvCtrlWirelessSwitch(1);
            break;
        case CMD_CODE_SYS_SLEEP:
            handleTdscdmaTlvCtrlWirelessSwitch(0);
            break;
		case CMD_CODE_SYS_EXIT:	
            TDSCDMALogError("system is exiting, closing wcdma socket.");
            release_connection(tdscdma_udp_conn_t);
			break;
        default:
            TDSCDMALogWarning("Unknown cmdCode = %x.",  pCmd->cmdCode);
            break;
    }
}

void handleTdscdmaTlvCtrlRestartMsg()
{
    sendTdscdmaReboot(0);    
    buildAndSendTdscdmaTlvCmdSetResponseMsg(CMD_SET, PARA_VALUE_RESULT_SUCCESS, 0,0);
}

void handleTdscdmaTlvCtrlWirelessSwitch(U32 rfSwitch)
{
    if(getTdscdmaModuleState() == TDSCDMA_MODULE_RUNNING)
    {
        char buf[MSG_MAX_LENGTH] = {0};
        U32  *result;

        GeneralHeader *msg = (GeneralHeader *)buf;

        msg->mjVer = MSG_TDSCDMA_MJVER;
        msg->mnVer = MSG_TDSCDMA_MNVER;
        msg->messageId = htonl(MSG_SET_RF_SWITCH);

        result = (U32 *)(buf + sizeof(GeneralHeader));
        *result = htonl(rfSwitch);

        msg->length = htonl(sizeof(U32));
        msg->sessionId = htonl(globalSession);

        send_tdscdma_udp_msg((char *)msg, sizeof(U32) + GENERAL_HEADER_LENGTH, globalSession);
        globalSession++;
    }
    else
    {
         buildAndSendTdscdmaTlvCmdSetResponseMsg(CMD_SET, PARA_VALUE_RESULT_SUCCESS, 0,0);
    }
}

void handleTdscdmaTlvCtrlSniffer(PCMDHEADER pCmd)
{
    if(getTdscdmaModuleState() == TDSCDMA_MODULE_RUNNING)
    {
        char buf[MSG_MAX_LENGTH] = {0};
        U32  length;

        MsgSetScanCell   *pScan;
        GeneralHeader *msg = (GeneralHeader *)buf;

        msg->mjVer = MSG_TDSCDMA_MJVER;
        msg->mnVer = MSG_TDSCDMA_MNVER;
        msg->messageId = htonl(MSG_GET_SCAN_CELL);

        pScan = (MsgSetScanCell *)(buf + sizeof(GeneralHeader));
        pScan->scan_type = 0;

        msg->length = sizeof(MsgSetScanCell);
        msg->sessionId = htonl(globalSession);

        length = msg->length + sizeof(GeneralHeader);    
        send_tdscdma_udp_msg((char *)msg, sizeof(MsgSetScanCell) + GENERAL_HEADER_LENGTH, globalSession++);
    }
    else
    {
        buildAndSendTdscdmaTlvCmdSetResponseMsg(CMD_SET, PARA_VALUE_RESULT_SUCCESS, 0,0);
    }
}

void handleTdscdmaTlvSetTxAttuation(PCMDHEADER pCmd)
{
    PPARAM pParam =(PPARAM)(pCmd+1);

    U32 len = pCmd->cmdLength;
    U32 paraType;
    U32 paraLength;
    U8* paraValue;
    UNPACK_RESULT uprc; 
    U32 attuation = 0;
	
	tdscdmaParam_t *pTdscdmaParam = getTdscdmaParam();   
    while((uprc=CM_paraUnpackPara(&pParam, &len, &paraType, &paraLength,&paraValue)) == UNPACK_OK)
    {
        switch(paraType)
        {
            case PARA_TYPE_TX_ATTUATION:
                attuation = *((U32 *) paraValue);
                pTdscdmaParam->txPower = attuation;
                break;
            default:
                TDSCDMALogError("Unknown paramType error in received cmdcode = %x",   pCmd->cmdCode);

                buildAndSendTdscdmaTlvCmdSetResponseMsg(CMD_SET, PARA_VALUE_RESULT_FAILED, PARA_TYPE_ERROR_CODE, PARA_VALUE_ERROR_UNKNOWN_PARATYPE);
                break;
        }
    }

    if( uprc == UNPACK_ERROR )
    {
        TDSCDMALogError(" Parameter unpack error in received cmdcode = %x", pCmd->cmdCode);

        buildAndSendTdscdmaTlvCmdSetResponseMsg(CMD_SET, PARA_VALUE_RESULT_FAILED, PARA_TYPE_ERROR_CODE, PARA_VALUE_ERROR_ILLEGAL_PARA_STRUCT);
        
        return;
    }

    if(getTdscdmaModuleState() == TDSCDMA_MODULE_RUNNING ||
	   getTdscdmaModuleState() == TDSCDMA_MODULE_CONFIGED)
    {
        sendTdscdmaConfigCell(0);
    }
	
    //send success response
    buildAndSendTdscdmaTlvCmdSetResponseMsg(CMD_SET, PARA_VALUE_RESULT_SUCCESS, 0, 0);
}

void handleTdscdmaTlvConfigWirelessMsg(PCMDHEADER pCmd)
{
    PPARAM pParam =(PPARAM)(pCmd+1);
    U32 len = pCmd->cmdLength;
    U32 paraType;
    U32 paraLength;
    U8* paraValue;
    UNPACK_RESULT uprc; 
    bool rc = false;
    bool isAutoLac = false;
    bool isMnc = false;
    bool isMcc = false;
    bool isPsc = false;
    bool isArfcn = false;
    bool isRac = false;
    bool isLac = false;
    bool isCellId = false;
	bool isTotal = false;
	bool isDac = false;
	bool isTxPower = false;
		
	//for building message
    //char buf[MSG_MAX_LENGTH]={0x0};
	
	tdscdmaParam_t *pTdscdmaParam = getTdscdmaParam();
    while((uprc=CM_paraUnpackPara(&pParam, &len, &paraType, &paraLength,&paraValue)) == UNPACK_OK)
    {
        switch(paraType)
        {
            case PARA_TYPE_TDSCDMA_WIRELESS_CONFIGURATION:
				isTotal = true;
				memcpy(pTdscdmaParam, paraValue, sizeof(tdscdmaParam_t));
                break;
            case PARA_TYPE_TDSCDMA_WIRELESS_CONFIG_MNC:
				isMnc = true;
                pTdscdmaParam->mnc = *((U32 *) paraValue);
                break;	
            case PARA_TYPE_TDSCDMA_WIRELESS_CONFIG_MCC:
				isMcc = true;
                pTdscdmaParam->mcc = *((U32 *) paraValue);
                break;	
            case PARA_TYPE_TDSCDMA_WIRELESS_CONFIG_LAC:	
				isLac= true;
                pTdscdmaParam->lac = *((U32 *) paraValue);
                break;	
            case PARA_TYPE_TDSCDMA_WIRELESS_CONFIG_RAC:		
                isRac = true;
                pTdscdmaParam->rac = *((U32 *) paraValue);
                break;
            case PARA_TYPE_TDSCDMA_WIRELESS_CONFIG_ARFCN:	
				isArfcn = true;
                pTdscdmaParam->arfcn = *((U32 *) paraValue);
                break;
            case PARA_TYPE_TDSCDMA_WIRELESS_CONFIG_PSC:	
				isPsc = true;
                pTdscdmaParam->psc = *((U32 *) paraValue);
                break;
            case PARA_TYPE_TDSCDMA_WIRELESS_CONFIG_CELLID:	
				isCellId = true;
                pTdscdmaParam->psc = *((U32 *) paraValue);
                break;				
            case PARA_TYPE_TDSCDMA_WIRELESS_CONFIG_AUTOLAC:
				isAutoLac = true;
                pTdscdmaParam->autolac = *((U32 *) paraValue);
                break;
            case PARA_TYPE_TDSCDMA_WIRELESS_CONFIG_DAC:
				isDac = true;
                pTdscdmaParam->sac = *((U32 *) paraValue);
                break;
            case PARA_TYPE_TDSCDMA_WIRELESS_CONFIG_TXPOWER:
				isTxPower = true;
                pTdscdmaParam->txPower = *((U32 *) paraValue);
                break;
            default:
                TDSCDMALogError("Unknown paramType error in received cmdcode = %x",   pCmd->cmdCode);
                rc = buildAndSendTdscdmaTlvCmdSetResponseMsg(CMD_SET, PARA_VALUE_RESULT_FAILED, PARA_TYPE_ERROR_CODE, PARA_VALUE_ERROR_UNKNOWN_PARATYPE);
                break;
        }
    }

    if( uprc == UNPACK_ERROR )
    {
        TDSCDMALogError("Parameter unpack error in received cmdcode = %x", pCmd->cmdCode);

        if (!rc)  buildAndSendTdscdmaTlvCmdSetResponseMsg(CMD_SET, PARA_VALUE_RESULT_FAILED, PARA_TYPE_ERROR_CODE, PARA_VALUE_ERROR_ILLEGAL_PARA_STRUCT);
        
        return;
    }

	if(isTotal)
	{
		if ( pTdscdmaParam == NULL )
		{
			TDSCDMALogError("NULL while update total tdscdma parameters cmdcode = %x",	pCmd->cmdCode);		
			rc = buildAndSendTdscdmaTlvCmdSetResponseMsg(CMD_SET, PARA_VALUE_RESULT_FAILED, PARA_TYPE_ERROR_CODE, PARA_VALUE_ERROR_INVALID_PARAMETERS);
			return;
		}
	}

    if(getTdscdmaModuleState() == TDSCDMA_MODULE_IDLE)
    {
         setTdscdmaModuleState(TDSCDMA_MODULE_PRECONFIG);
    }
    else if(getTdscdmaModuleState() == TDSCDMA_MODULE_RUNNING)
	{
        sendTdscdmaConfigCell(0);
	}
	else
	{
	   setTdscdmaModuleState(TDSCDMA_MODULE_CONFIGING);
	   TDSCDMALogNotice("tdscdma board is not ready yet.");
	}

	buildAndSendTdscdmaTlvCmdSetResponseMsg(CMD_SET, PARA_VALUE_RESULT_SUCCESS, 0, 0);
}

/**
 ****************************************************************************************
 * @brief   build and send cmd set response to dispatcher module, 
 * @param   result            -  failed or success
 * @return  none
 ****************************************************************************************
 */ 
bool buildAndSendTdscdmaTlvCmdSetResponseMsg(U8 cmdType, U32 result, U32 paraType, U32 paraValue)
{
    PCMDHEADER cmdHdr = getTdscdmaTlvCmdHeader(cmdType);

    if (cmdHdr->cmdCode == INVALID_CMD_CODE)
    {
        //no need send reponse 
        TDSCDMALogNotice("no cmd code for cmdType = %x", cmdType);
        return true;
    }

    U8 cmdResponse = (cmdType & 0xf) | 0x10;
   
    if(result == PARA_VALUE_RESULT_FAILED)
    {
        CM_SendMsg_2Para(getTdscdmaTlvSrcID(cmdType), MODULE_TDSCDMA_CAP, MSG_TYPE_COMMAND, cmdResponse, cmdHdr->cmdCode, cmdHdr->cmdIndex,
                         PARA_TYPE_RESULT, 4, (U8 *)&result, paraType, 4, (U8 *)&paraValue);
    }
    else
    {
        CM_SendMsg_1Para(getTdscdmaTlvSrcID(cmdType), MODULE_TDSCDMA_CAP, MSG_TYPE_COMMAND, cmdResponse, cmdHdr->cmdCode, cmdHdr->cmdIndex,
                         PARA_TYPE_RESULT, 4, (U8 *)&result);
    }

    //reset the cmd set for next cmd message
    cmdHdr->cmdCode = INVALID_CMD_CODE;

    return true;
}

/**
 ****************************************************************************************
 * @brief   build and send alarm to dispatcher module, 
 * @return  none
 ****************************************************************************************
 */
void tdscdmaBuildAndSendTlvEventNoParam(U16 moduleID, U16 cmdCode)
{
    CM_SendMsg_noPara(moduleID, MODULE_TDSCDMA_CAP,MSG_TYPE_COMMAND, CMD_EVENT, cmdCode, 0);
	  	  	  
    return;
}

/**
 ****************************************************************************************
 * @brief   build and send alarm to dispatcher module, 
 * @param   paramType         -  alarm type
 * @param   paramValue        -  alarm value
 * @return  none
 ****************************************************************************************
 */
void tdscdmaBuildAndSendTlvEvent(U16 moduleID, U16 cmdCode, U32 paramType, U32 paramValue)
{
    CM_SendMsg_1Para(moduleID, MODULE_TDSCDMA_CAP,MSG_TYPE_COMMAND, CMD_EVENT, cmdCode, 0,
                     paramType, 4, (U8 *) &paramValue);    
	  	  	  
    return;
}

void reportHeartBeatTdscdmaModuleStatus()
{
    tdscdmaModuleState_t state = getTdscdmaModuleState();
    
    U32 wirelessState = PARA_VALUE_TDSCDMA_WILELESS_OFF;

    if ( state == TDSCDMA_MODULE_RUNNING )
           wirelessState = PARA_VALUE_TDSCDMA_WILELESS_ON;

    CM_SendMsg_1Para(MODULE_SYSTEM, MODULE_TDSCDMA_CAP, MSG_TYPE_COMMAND, CMD_EVENT, CMD_TDSCDMA_EVT_STATUS, 0,
                     PARA_TYPE_TDSCDMA_WILELESS_STATE, 4, (U8*)&wirelessState);
}
/**
 ****************************************************************************************
 * @brief   build and report tdscdma module status, 
 * @return  none
 ****************************************************************************************
 */
void buildAndReportTdscdmaModuleStatus()
{
    tdscdmaModuleState_t state = getTdscdmaModuleState();
    U32  msgLength = strlen(tdscdmaStatesStr[state]);

    PCMDHEADER cmdHdr = getTdscdmaTlvCmdHeader(CMD_GET);

    if (cmdHdr->cmdCode == INVALID_CMD_CODE)
    {
    	  //no need send reponse 
    	  return;
    }

    CM_SendMsg_1Para(getTdscdmaTlvSrcID(CMD_GET), MODULE_TDSCDMA_CAP,MSG_TYPE_COMMAND, CMD_GET_RESPONSE, cmdHdr->cmdCode, cmdHdr->cmdIndex,
                     PARA_TYPE_TDSCDMA_MODULE_STATUS, msgLength, (U8 *)tdscdmaStatesStr[state]);

    //reset the cmd set for next cmd message
    cmdHdr->cmdCode = INVALID_CMD_CODE;
}

/**
 ****************************************************************************************
 * @brief   build and report tdscdma configuration 
 * @return  none
 ****************************************************************************************
 */
void buildAndReportTdscdmaConfiguration(tdscdmaParam_t *param)
{
    PCMDHEADER cmdHdr = getTdscdmaTlvCmdHeader(CMD_GET);
    if(cmdHdr->cmdCode == CMD_TDSCDMA_GET_MODULE_CFG)
    {
        CM_SendMsg_1Para(getTdscdmaTlvSrcID(CMD_GET), MODULE_TDSCDMA_CAP, MSG_TYPE_COMMAND,CMD_GET_RESPONSE, cmdHdr->cmdCode, cmdHdr->cmdIndex,
                         PARA_TYPE_TDSCDMA_WIRELESS_CONFIGURATION, sizeof(tdscdmaParam_t), (U8 *)param);

		//reset the cmd set for next cmd message
		cmdHdr->cmdCode = INVALID_CMD_CODE;
    }
	else
	{
		TDSCDMALogWarning("configuration command was flushed by the following command");
		buildAndSendTdscdmaTlvCmdSetResponseMsg(CMD_GET, PARA_VALUE_RESULT_FAILED, PARA_TYPE_ERROR_CODE, PARA_VALUE_ERROR_UNKNOWN_PARATYPE);
	}
}

tdscdmaModuleState_t getTdscdmaModuleState()
{
    tdscdmaModuleState_t state;

    pthread_mutex_lock(&tdscdmaMutex);    
    state = gTdscdmaState;
    pthread_mutex_unlock(&tdscdmaMutex);

    TDSCDMALogDebug("Get TDSCDMA module state: %s", tdscdmaStatesStr[state]);

    return state;
}

void setTdscdmaModuleState(tdscdmaModuleState_t state)
{
    tdscdmaModuleState_t lastState = gTdscdmaState;
    pthread_mutex_lock(&tdscdmaMutex);    
    gTdscdmaState = state;
    pthread_mutex_unlock(&tdscdmaMutex);
    if ((lastState != TDSCDMA_MODULE_RUNNING) && (state == TDSCDMA_MODULE_RUNNING))
    {
        tdscdmaBuildAndSendTlvEventNoParam(MODULE_INTF, CMD_TDSCDMA_EVT_SYNC);
        TDSCDMALogNotice("tdscdma module is running");
    }
    TDSCDMALogDebug("Set TDSCDMA module state: %s", tdscdmaStatesStr[state]);
}

void setTdscdmaModuleRecvImsi()
{
    pthread_mutex_lock(&tdscdmaMutex);    
    tdscdmaHavedRecvImsi = true;
    pthread_mutex_unlock(&tdscdmaMutex);
}

bool getTdscdmaModuleRecvImsi()
{
    bool recv = false;
    pthread_mutex_lock(&tdscdmaMutex);    
    recv = tdscdmaHavedRecvImsi;
    tdscdmaHavedRecvImsi = false;
    pthread_mutex_unlock(&tdscdmaMutex);
    return recv;
}


/***************************************************************************************/
/* @brief   init udp connection context,                                               */ 
/* @param   msg         -  udp msg pointer                                             */ 
/* @param   length      -  udp msg length                                              */
/* @return  none                                                                       */ 
/***************************************************************************************/ 
void send_tdscdma_udp_msg(const char *msg, U16 length, U32 sessionId)
{
    GeneralHeader  *hdr = (GeneralHeader *)msg;
    
    send_msg(tdscdma_udp_conn_t, (const char*)msg, length);

    //backup for re-sending because of no response or error occur 
    if(sessionId != 0)
       tdscdmaBackupLatestUdpMsg(msg, length, sessionId);

#if(TDSCDMA_DEBUG == 1)
    stringstream logstream;
    logstream << "Send TDSCDMA UDP MSGID: " << hex << ntohl(hdr->messageId) <<  endl;
	TDSCDMALogDebug("%s", logstream.str().c_str());
#endif
}

void send_common_tdscdma_msg(U32 msgId, U32 sessionId)
{
    GeneralHeader msg;
    U32 sid = (sessionId == 0) ? globalSession : sessionId;

	msg.sessionId = htonl(sid);
	msg.mjVer = MSG_TDSCDMA_MJVER;
	msg.mnVer = MSG_TDSCDMA_MNVER;
	msg.messageId = htonl(msgId);
    msg.reserved = 0;
	msg.length = 0;

    if(sessionId == 0)
    {
        send_tdscdma_udp_msg((char *)&msg, sizeof(GeneralHeader), sid);
    }
    else
    {
        send_tdscdma_udp_msg((char *)&msg, sizeof(GeneralHeader), 0);
    }

    globalSession++;
}

void resetBackedupMsgBuffer(U32 sessionId)
{
	for(int i = 0; i < BACKED_MSG_NUMBER; i++)
	{
	   if(tdscdmaBackedMsg[i].sessionId == sessionId)
	   	{
	   	   tdscdmaBackedMsg[i].sessionId = 0;
		   memset(tdscdmaBackedMsg[i].msg, 0x0, BACKED_MAX_LENGTH);
		   tdscdmaBackedMsg[i].len = 0;
	   	}
	}
}
/**
 ****************************************************************************************
 * @brief   resending latest backup udp message 
 * @param   msg         -  udp msg pointer
 * @param   length      -  udp msg length
 * @return  none
 ****************************************************************************************
 */ 
void resendingTdscdmaBackupUdpMsg(U32 sessionId)
{
    for (int i = 0; i < BACKED_MSG_NUMBER; i++)
    {
       if(tdscdmaBackedMsg[i].sessionId == sessionId)
       send_tdscdma_udp_msg((const char *)tdscdmaBackedMsg[i].msg, tdscdmaBackedMsg[i].len, 0);
    }
}

/**
 ****************************************************************************************
 * @brief   backup latest udp message for re-sending, 
 * @param   msg         -  udp msg pointer
 * @param   length      -  udp msg length
 * @return  none
 ****************************************************************************************
 */ 
void tdscdmaBackupLatestUdpMsg(const char *msg, U16 msglen, U32 sessionId)
{
    for(int i = 0; i < BACKED_MSG_NUMBER; i++)
    {
       if(sessionId == tdscdmaBackedMsg[i].sessionId)
	   	   break;

	   if(tdscdmaBackedMsg[i].sessionId == 0)
	   {
       	   memcpy(tdscdmaBackedMsg[i].msg, msg, msglen);    
           tdscdmaBackedMsg[i].len = msglen;
	   }
    }
}

void sendTdscdmaInitAck(U32 sessionId)
{
    char buf[MSG_MAX_LENGTH] = {0};
    GeneralHeader *hdr = (GeneralHeader *)buf;

	hdr->sessionId = htonl(sessionId);
	hdr->mjVer = MSG_TDSCDMA_MJVER;
	hdr->mnVer = MSG_TDSCDMA_MNVER;
	hdr->messageId = htonl(MSG_INIT_ACK);	
	hdr->length = htonl(sizeof(U32));

    //access allow
    U32 *access = (U32 *)(buf + GENERAL_HEADER_LENGTH);
    *access = 0;

    send_tdscdma_udp_msg(buf, sizeof(U32) + GENERAL_HEADER_LENGTH, 0);

    globalSession++;    
}

void sendTdscdmaInitConfig(U32 sessionId)
{
#if 1
    char buf[MSG_MAX_LENGTH] = {0};

    MsgInitConfig *pInitConfig;

	tdscdmaParam_t *pParam = getTdscdmaParam();

    GeneralHeader *msg = (GeneralHeader *)buf;
	msg->sessionId = htonl(globalSession);
	msg->mjVer = MSG_TDSCDMA_MJVER;
	msg->mnVer = MSG_TDSCDMA_MNVER;
	msg->messageId = htonl(MSG_INIT_CONFIGURE);

    pInitConfig = (MsgInitConfig *)(buf + GENERAL_HEADER_LENGTH);
	//copy gw ip
	memcpy(pInitConfig->gateway.femtoGW_address, TDSCDMA_MODULE_IP,15);
	pInitConfig->gateway.server_port = htonl(atoi(TDSCDMA_MODULE_UDP_PORT));
	pInitConfig->gateway.local_port = htonl(atoi(TDSCDMA_MODULE_UDP_PORT));
	
	pInitConfig->cell.fap_txPower = htons(pParam->txPower);
	pInitConfig->cell.cell_parameter_id = htons(pParam->psc);
	pInitConfig->cell.uarfcn = htons(pParam->arfcn);

    //plmn id
	pInitConfig->cn.plmn_id.mcc.date[0] = 0x04;
	pInitConfig->cn.plmn_id.mcc.date[1] = 0x06;
	pInitConfig->cn.plmn_id.mcc.date[2] = 0x00;
	pInitConfig->cn.plmn_id.mnc.date[0] = 0x00;
	pInitConfig->cn.plmn_id.mnc.date[1] = 0x00;
	pInitConfig->cn.plmn_id.mnc.date[2] = 0x00;	
	pInitConfig->cn.plmn_id.mnc.n = htons(0x0002);

    //equivlent plmn id
	pInitConfig->cn.equiv_plmn_id.mcc.date[0] = 0x04;
	pInitConfig->cn.equiv_plmn_id.mcc.date[1] = 0x06;
	pInitConfig->cn.equiv_plmn_id.mcc.date[2] = 0x00;
	pInitConfig->cn.equiv_plmn_id.mnc.date[0] = 0x00;
	pInitConfig->cn.equiv_plmn_id.mnc.date[1] = 0x02;
	pInitConfig->cn.equiv_plmn_id.mnc.date[2] = 0x00;
	pInitConfig->cn.plmn_id.mnc.n = htons(0x0002);
	
	pInitConfig->cn.sac = htons(pParam->sac);
	pInitConfig->cn.lac = htons(pParam->lac);
	pInitConfig->cn.rac = htons(pParam->rac);

	msg->length = htonl(sizeof(MsgInitConfig));
	send_tdscdma_udp_msg(buf, sizeof(MsgInitConfig) + GENERAL_HEADER_LENGTH, globalSession);
#else
    send_tdscdma_udp_msg(hardInitConfig, sizeof(hardInitConfig), globalSession);   
#endif
	globalSession++;
}

void sendTdscdmaConfigCell(U32 sessionId)
{
    char buf[MSG_MAX_LENGTH] = {0};
    MsgSetCell *pCell;
	//MsgRemCellInd * pRem = getRemCellInd();
	tdscdmaParam_t *pParam = getTdscdmaParam();
    GeneralHeader *msg = (GeneralHeader *)buf;
	
	msg->mjVer = MSG_TDSCDMA_MJVER;
	msg->mnVer = MSG_TDSCDMA_MNVER;
	msg->messageId = htonl(MSG_SET_CELL);
	msg->sessionId = htonl(globalSession);

	pCell = (MsgSetCell *)(buf + sizeof(GeneralHeader));
	//fill msg
	//pCell->uarfcn = pRem->rem_cell.UARFCN;
	//pCell->cell_parameter_id = pRem->rem_cell.CellParametersId;
	pCell->cell_parameter_id = htons(pParam->psc);
	pCell->uarfcn = htons(pParam->arfcn);
    pCell->fap_txPower = htons(pParam->txPower);

	msg->length = htonl(sizeof(MsgSetCell));
	
	send_tdscdma_udp_msg(buf, sizeof(MsgSetCell) + GENERAL_HEADER_LENGTH, globalSession);

	globalSession++;
}

void sendTdscdmaGetScanCell(U32 sessionId)
{
    char buf[MSG_MAX_LENGTH] = {0};
	U32  length;

	MsgGetScanCell   *pScan;
    GeneralHeader *msg = (GeneralHeader *)buf;
	
	msg->mjVer = MSG_TDSCDMA_MJVER;
	msg->mnVer = MSG_TDSCDMA_MNVER;
	msg->messageId = htonl(MSG_GET_SCAN_CELL);

	pScan = (MsgGetScanCell *)(buf + sizeof(GeneralHeader));
	pScan->scan_type = 0;
	pScan->scan_on_boot = 0;
	pScan->scan_type = 0;
	
	msg->length = sizeof(MsgSetScanCell);
 	msg->sessionId = htonl(globalSession);

    length = msg->length + sizeof(GeneralHeader);    
	send_tdscdma_udp_msg(buf, sizeof(MsgSetScanCell) + sizeof(GeneralHeader), globalSession++);     
}

void sendTdscdmaCellStateAck(U32 sessionId)
{
    send_common_tdscdma_msg(MSG_CELL_STATE_ACK,sessionId);
}

void sendTdscdmaHeartbeat()
{
    send_common_tdscdma_msg(MSG_HEARTBEAT, 0);
}

void sendTdscdmaReboot(U32 rebootType)
{
    char buf[MSG_MAX_LENGTH] = {0};
	U32  length;
	U32  *result;
	
    GeneralHeader *msg = (GeneralHeader *)buf;
	
	msg->mjVer = MSG_TDSCDMA_MJVER;
	msg->mnVer = MSG_TDSCDMA_MNVER;
	msg->messageId = htonl(MSG_REBOOT);

	result = (U32 *)(buf + sizeof(GeneralHeader));
	*result = htonl(rebootType);
	
	msg->length = htonl(sizeof(U32));
 	msg->sessionId = htonl(globalSession);

    length = msg->length + sizeof(GeneralHeader);    
	send_tdscdma_udp_msg((char *)msg, sizeof(U32) + GENERAL_HEADER_LENGTH, globalSession);
	globalSession++;
}
/**
 ****************************************************************************************
 * Handle configuration type message response
 *
 ****************************************************************************************
 */ 
void handleTdscdmaMsgInitConfigAck(const char* buf, ssize_t len)
{
    GeneralHeader *hdr = (GeneralHeader *)buf;
	resetBackedupMsgBuffer(ntohl(hdr->sessionId));
	
    U32   result = *((U32 *)(buf + GENERAL_HEADER_LENGTH));

    if(ntohl(result) == MSG_TDSCDMA_RESULT_OK)
    {
		setTdscdmaModuleState(TDSCDMA_MODULE_CONFIGED);
		//buildAndSendTdscdmaTlvCmdSetResponseMsg(CMD_SET, PARA_VALUE_RESULT_SUCCESS, 0, 0);
	    TDSCDMALogNotice("TDS NodeB init configuration success."); 		
        sendTdscdmaGetScanCell(0);
    }
	else
	{
		setTdscdmaModuleState(TDSCDMA_MODULE_PRECONFIG);	
		//buildAndSendTdscdmaTlvCmdSetResponseMsg(CMD_SET, PARA_VALUE_RESULT_FAILED, PARA_TYPE_ERROR_CODE, PARA_VALUE_ERROR_TDSCDMA_CONFIG_FAILED);	
		TDSCDMALogError("TDS NodeB init configuration failure.");  	
	}
}

void handleTdscdmaMsgRemCellInd(const char* buf, ssize_t len)
{
    MsgRemCellInd *pRemCell = (MsgRemCellInd *)(buf + GENERAL_HEADER_LENGTH);
	
	if(htonl(pRemCell->result) == MSG_TDSCDMA_RESULT_OK)
	{
	    TDSCDMALogNotice("Cell search success, Marco cell num %d", pRemCell->rem_cell_count);
		//memcpy(getRemCellInd(), pRemCell, sizeof(MsgRemCellInd));
	}
}

void handleTdscdmaMsgScanCellAck(const char* buf, ssize_t len)
{
    GeneralHeader *hdr = (GeneralHeader *)buf;
	U32 result = *((U32*)(buf + GENERAL_HEADER_LENGTH));

	for(int i = 0; i < BACKED_MSG_NUMBER; i++)
	{
	   if(tdscdmaBackedMsg[i].sessionId == hdr->sessionId)
	   	{
	   	   tdscdmaBackedMsg[i].sessionId = 0;
		   memset(tdscdmaBackedMsg[i].msg, 0x0, BACKED_MAX_LENGTH);
		   tdscdmaBackedMsg[i].len = 0;
	   	}
	}
	
	if(result == MSG_TDSCDMA_RESULT_OK)
	{
		TDSCDMALogError("TDSCDMA Cell Set success.");
		if (getTdscdmaModuleState() != TDSCDMA_MODULE_RUNNING)
		{
			handleTdscdmaPaCtrl(true, TDSCDMA_PA_TYPE_NOTHING);
			setTdscdmaModuleState(TDSCDMA_MODULE_RUNNING);
		}
	    
		
	}
	else
	{
		TDSCDMALogError("TDSCDMA Cell Scan failed.");
	}
} 

void handleTdscdmaMsgSetCellAck(const char* buf, ssize_t len)
{
    GeneralHeader *hdr = (GeneralHeader *)buf;
	U32 result = ntohl(*((U32*)(buf + GENERAL_HEADER_LENGTH)));

	for(int i = 0; i < BACKED_MSG_NUMBER; i++)
	{
	   if(tdscdmaBackedMsg[i].sessionId == hdr->sessionId)
	   	{
	   	   tdscdmaBackedMsg[i].sessionId = 0;
		   memset(tdscdmaBackedMsg[i].msg, 0x0, BACKED_MAX_LENGTH);
		   tdscdmaBackedMsg[i].len = 0;
	   	}
	}

    if(result == MSG_TDSCDMA_RESULT_OK)
    {
		TDSCDMALogNotice("TDSCDMA Cell Set Success.");
	    if (getTdscdmaModuleState() != TDSCDMA_MODULE_RUNNING)
		{
			handleTdscdmaPaCtrl(true, TDSCDMA_PA_TYPE_NOTHING);
			setTdscdmaModuleState(TDSCDMA_MODULE_RUNNING);
		}
	    
    }
    else
    {
		TDSCDMALogNotice("TDSCDMA Cell Set failed.");
	    setTdscdmaModuleState(TDSCDMA_MODULE_PRECONFIG);
    }
}

void handleTdscdmaMsgGetScanCellAck(const char* buf, ssize_t len)
{
    GeneralHeader *hdr = (GeneralHeader *)buf;

	for(int i = 0; i < BACKED_MSG_NUMBER; i++)
	{
	   if(tdscdmaBackedMsg[i].sessionId == hdr->sessionId)
	   	{
	   	   tdscdmaBackedMsg[i].sessionId = 0;
		   memset(tdscdmaBackedMsg[i].msg, 0x0, BACKED_MAX_LENGTH);
		   tdscdmaBackedMsg[i].len = 0;
	   	}
	}
	
	TDSCDMALogNotice("TDSCDMA Get Scan Cell ack.");
}

void handleTdscdmaMsgGetVersionAck(const char* buf, ssize_t len)
{
    GeneralHeader *hdr = (GeneralHeader *)buf;
	const char    *payload = buf + sizeof(GeneralHeader);

	for(int i = 0; i < BACKED_MSG_NUMBER; i++)
	{
	   if(tdscdmaBackedMsg[i].sessionId == hdr->sessionId)
	   	{
	   	   tdscdmaBackedMsg[i].sessionId = 0;
		   memset(tdscdmaBackedMsg[i].msg, 0x0, BACKED_MAX_LENGTH);
		   tdscdmaBackedMsg[i].len = 0;
	   	}
	}

    char hw[100];
	char sw[100];

	memcpy(hw, payload, 64);
    payload += 64;
	memcpy(sw, payload, 64);
		
	TDSCDMALogNotice("TDSCDMA Hw %s, Sw %s.", hw, sw);
}

void handleTdscdmaMsgGetRfSwitchAck(const char* buf, ssize_t len)
{
    GeneralHeader *hdr = (GeneralHeader *)buf;
	const char    *payload = buf + sizeof(GeneralHeader);

	for(int i = 0; i < BACKED_MSG_NUMBER; i++)
	{
	   if(tdscdmaBackedMsg[i].sessionId == hdr->sessionId)
	   	{
	   	   tdscdmaBackedMsg[i].sessionId = 0;
		   memset(tdscdmaBackedMsg[i].msg, 0x0, BACKED_MAX_LENGTH);
		   tdscdmaBackedMsg[i].len = 0;
	   	}
	}

	U32 result = ntohl(*(U32*)payload);
	if(result == 1)
	{
		TDSCDMALogNotice("TDSCDMA RF Open.");	   
	}
	else
	{
		TDSCDMALogNotice("TDSCDMA RF Close.");	   
	}		
}

void handleTdscdmaMsgSetRfSwitchAck(const char* buf, ssize_t len)
{
    GeneralHeader  *hdr = (GeneralHeader *)buf;
	const char *payload = buf + sizeof(GeneralHeader);

	for(int i = 0; i < BACKED_MSG_NUMBER; i++)
	{
	   if(tdscdmaBackedMsg[i].sessionId == hdr->sessionId)
	   	{
	   	   tdscdmaBackedMsg[i].sessionId = 0;
		   memset(tdscdmaBackedMsg[i].msg, 0x0, BACKED_MAX_LENGTH);
		   tdscdmaBackedMsg[i].len = 0;
	   	}
	}

	U32 result = ntohl(*(U32*)payload);
	if(result == 1)
	{
		TDSCDMALogNotice("TDSCDMA Set RF Open.");	   
	}
	else
	{
		TDSCDMALogNotice("TDSCDMA Set RF Close.");	   
	}		
}

void handleTdscdmaMsgGetSyncAck()
{

}

void handleTdscdmaMsgUeReport(const char* buf, ssize_t len)
{
    MsgUeReport *ueReport = (MsgUeReport *)(buf + GENERAL_HEADER_LENGTH);
    U32 count = ntohl(ueReport->UeIDcount);
 
    printf("UE count %d", count);
    fflush(stdout); 
	RESULT rc = RC_MOD_INVALID;	
	//U64 ctime = getTdscdmaCurrentTime();	
	U64 ctime = time(NULL);
	U8 imsi[20] = {0};	
	U8 imei[20] = {0};
	U8 slotId = TDSCDMA_SLOT; 

    for(U32 i = 0; i < count; i++)
    {
        for(U32 j = 0; j < 15; j++)
        {
            //transfer to ascii
            imsi[j] = ueReport->UeIdRpt[i].imsi[j] + 0x30;
            imei[j] = ueReport->UeIdRpt[i].imei[j] + 0x30;
        }

        TDSCDMALogDebug("time= %llu  imsi = %s",  ctime, (char *)imsi);
        rc = CM_SendMsg_4Para(MODULE_DATAPRO, MODULE_TDSCDMA_CAP,MSG_TYPE_INTERNAL, CMD_EVENT, CMD_EVT_EUTRAN_UEID, 0, 
                PARA_TYPE_EUTRAN_TIME, 8, (U8 *)&ctime, 
                PARA_TYPE_EUTRAN_UEID_IMSI, UE_ID_LENGTH, (U8 *)imsi,
                PARA_TYPE_EUTRAN_UEID_IMEI, UE_ID_LENGTH, (U8 *)imei, 
                PARA_TYPE_EUTRAN_BBU_SLOT_ID, 1, (U8 *)&slotId);
        setTdscdmaModuleRecvImsi();
        increaseSendCounter(rc);
    }
}

/**
 ****************************************************************************************
 * Handle parmater type message
 * 1. report
 * 2. response
 ****************************************************************************************
 */ 
void handleTdscdmaMsgInit(const char* buf, ssize_t len)
{
    GeneralHeader *hdr = (GeneralHeader *)buf;
    const char *ptr = buf + GENERAL_HEADER_LENGTH;
    
    char serial[100];
	char product[100];
    char version[100];
   
    if(getTdscdmaModuleState() == TDSCDMA_MODULE_PRECONFIG ||
	   getTdscdmaModuleState() == TDSCDMA_MODULE_NSYNC ||
       getTdscdmaModuleState() == TDSCDMA_MODULE_RESTART)
    {
		//send back init ack to bts
		sendTdscdmaInitAck(ntohl(hdr->sessionId));
    
	    memcpy(serial, ptr, 64);
        ptr += 64;
	    memcpy(product, ptr, 64);
        ptr += 64;
        memcpy(version, ptr, 64);
	    TDSCDMALogNotice("TDSCDMA serial %s, product %s, version %s.", serial, product, version);
        sendTdscdmaInitConfig(0);

        setTdscdmaModuleState(TDSCDMA_MODULE_CONFIGING);        
    }
}

void handleMsgALarmInd(const char* buf, ssize_t len)
{
}

void handleTdscdmaMsgSetScanCellAck(const char* buf, ssize_t len)
{

}

void handleTdscdmaMsgGetSyncAck(const char* buf, ssize_t len)
{
} 

void handleTdscdmaMsgHeartBeatAck(const char* buf, ssize_t len)
{
	//for sync 
	tdscdmaHbCounter++;
}

void handleTdscdmaMsgHeartBeat(const char* buf, ssize_t len)
{
    GeneralHeader *hdr = (GeneralHeader *)buf;
    send_common_tdscdma_msg(MSG_HEARTBEAT_ACK, ntohl(hdr->sessionId));

    if(getTdscdmaModuleState() == TDSCDMA_MODULE_PRECONFIG)
    {
        sendTdscdmaReboot(1);
    }

	//for sync 
	tdscdmaHbCounter++;
}

void handleTdscdmaMsgRebootAck(const char* buf, ssize_t len)
{
    GeneralHeader *hdr = (GeneralHeader *)buf;

	for(int i = 0; i < BACKED_MSG_NUMBER; i++)
	{
	   if(tdscdmaBackedMsg[i].sessionId == hdr->sessionId)
	   	{
	   	   tdscdmaBackedMsg[i].sessionId = 0;
		   memset(tdscdmaBackedMsg[i].msg, 0x0, BACKED_MAX_LENGTH);
		   tdscdmaBackedMsg[i].len = 0;
	   	}
	}

    setTdscdmaModuleState(TDSCDMA_MODULE_RESTART);
}

void handleTdscdmaMsgCellState(const char* buf, ssize_t len)
{
    GeneralHeader *hdr = (GeneralHeader *)buf;
    MsgCellState *cellState = (MsgCellState *)(buf + GENERAL_HEADER_LENGTH);
    U32 state = ntohl(cellState->state);
	
    TDSCDMALogNotice("sync state %s, uarfcn %d, psc %d", (state == 0) ? "ok" : "nok", 
		              ntohs(cellState->uarfcn), ntohs(cellState->cell_parameter_id));
    printf("sync state %s, uarfcn %d, psc %d", (state == 0) ? "ok" : "nok", 
		              ntohs(cellState->uarfcn), ntohs(cellState->cell_parameter_id));

    fflush(stdout);

	sendTdscdmaCellStateAck(ntohl(hdr->sessionId));

    if(getTdscdmaParam()->sac)
    {
       sendTdscdmaConfigCell(0);
    }

    if (getTdscdmaModuleState() != TDSCDMA_MODULE_RUNNING)
	{
		handleTdscdmaPaCtrl(true, TDSCDMA_PA_TYPE_NOTHING);
		setTdscdmaModuleState(TDSCDMA_MODULE_RUNNING);
	}
	    
}

/*
 * callback func to handle message of a UDP connection.
 */
static void handle_tdscdma_udp_message(struct conn_t* c, const char* buf, ssize_t len)
{
	GeneralHeader *msg = (GeneralHeader *)buf; 
	
#if (TDSCDMA_DEBUG == 1)
	stringstream logString;
	TDSCDMALogDebug( "UDP Msg ID: %x \n", msg->messageId);
	{
	   for (int i = 0; i < len; i++)
	   {
		   logString << std::hex << (U8)buf[i];
		   logString <<" ";
	   }
	   
	   logString << endl;	
	   TDSCDMALogDebug( logString.str().c_str());
	}
#endif
	
	switch (ntohl(msg->messageId))
	{
		case MSG_INIT:
			handleTdscdmaMsgInit(buf, len);	
			break;
		case MSG_HEARTBEAT:
			handleTdscdmaMsgHeartBeat(buf, len);
			break;
		case MSG_HEARTBEAT_ACK:
			handleTdscdmaMsgHeartBeatAck(buf, len);
			break;
		case MSG_INIT_CONFIGURE_ACK:
			handleTdscdmaMsgInitConfigAck(buf, len);
			break;
		case MSG_REM_CELL_IND:
			handleTdscdmaMsgRemCellInd(buf, len);
			break;			
		case MSG_SET_SCAN_CELL_ACK:
			handleTdscdmaMsgSetScanCellAck(buf, len);
			break;
		case MSG_ALARM_IND:
			handleMsgALarmInd(buf, len);
			break;
	    case MSG_SET_SYNC_ACK:	
	    	handleTdscdmaMsgGetSyncAck(buf, len); 
			break;				 
		case MSG_SET_CELL_ACK:		 
			handleTdscdmaMsgSetCellAck(buf, len);
			break;
		case MSG_GET_SCAN_CELL_ACK:
			handleTdscdmaMsgGetScanCellAck(buf, len);			
			break;
		case MSG_GET_RF_SWITCH_ACK:
			handleTdscdmaMsgGetRfSwitchAck(buf, len);		   
			break;
		case MSG_SET_RF_SWITCH_ACK:
            handleTdscdmaMsgSetRfSwitchAck(buf, len);
			break;
		case MSG_GET_VERSION_ACK:
			handleTdscdmaMsgGetVersionAck(buf, len);			 
			break; 
		case MSG_REBOOT_ACK:
			handleTdscdmaMsgRebootAck(buf, len);
			break;
		case MSG_CELL_STATE:
			handleTdscdmaMsgCellState(buf, len);
			break;
		case MSG_UEID_RPT:
			handleTdscdmaMsgUeReport(buf, len);				
			break;
		default:
		    TDSCDMALogNotice( "Unknown msg code: %02x.", msg->messageId);		  
		    break;
	}
}

static void on_close(struct conn_t* c)
{
    /* do nothing */
    release_connection(c);
}

static void on_error(struct conn_t* c)
{
    /* do nothing */
    release_connection(c);
}

static struct conn_cb_t udp_callback = {
       handle_tdscdma_udp_message,
       on_close,
       on_error
};

bool init_tdscdma_udp_context(sockaddr_in *remote_addr, sockaddr_in* local_addr)
{
    conn_context_init(&tdscdma_udp_ctxt);

    /*
     * make a udp connecton to a remote peer 
     */
    tdscdma_udp_conn_t = make_udpconn_to(&tdscdma_udp_ctxt, remote_addr, &udp_callback);
    
    /*
     * bind local address for receiving msg from remote peer
     */
    bind_local_address(tdscdma_udp_conn_t, local_addr);
    
    return true;
}

static void* tdscdma_udp_task_thread(void *arg __attribute__((unused)))
{
    TDSCDMALogNotice("tdscdma_udp_task_thread thread id is %lu.", pthread_self()); 
    pthread_setname_np(pthread_self(), "tdscdma_udp_task");

     /*
     * start main loop to handle network messasge
     *
     */
    main_loop(&tdscdma_udp_ctxt);

    TDSCDMALogNotice("Exiting the tdscdma_udp_task_thread thread.");
    pthread_exit( (void*)0 );
}

bool initTdscdmaUdpMsgTask()
{
    pthread_t       thread;
    pthread_attr_t  attr;
    struct sched_param sched;
    int32_t minAllowedPrio, maxAllowedPrio;
    int32_t schedPolicy = SCHED_OTHER;
    int32_t schedPriority = 0;

    if( pthread_attr_init(&attr) )
    {
        TDSCDMALogError("pthread_attr_init failed : %s.", strerror(errno));
        return false;
    }

    if( pthread_attr_setinheritsched(&attr, PTHREAD_EXPLICIT_SCHED) )
    {
        TDSCDMALogError("pthread_attr_setinheritsched failed : %s.", strerror(errno));
        return false;
    }

    if( pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED) )
    {
        TDSCDMALogError("pthread_attr_setdetachstate failed: %s.", strerror(errno));
        return false;
    }

    /****************** Setup scheduling **************************/
    /* If we are not superuser, don't try changing scheduling */
    if( (getuid() != 0) && (schedPolicy != SCHED_OTHER) )
    {
        TDSCDMALogError("Don't have permission for ttisched != OTHER.");
        return false;
    }

    if( schedPolicy == SCHED_OTHER && schedPriority != 0 )
    {
        TDSCDMALogError("maxp %d invalid for ttisched OTHER (must be 0).", schedPriority);
        return false;
    }

    if( (minAllowedPrio = sched_get_priority_min(schedPolicy)) < 0 )
    {
        TDSCDMALogError("sched_get_priority_min failed : %s", strerror(errno));
        return false;
    }

    if( (maxAllowedPrio = sched_get_priority_max(schedPolicy)) < 0)
    {
        TDSCDMALogError("sched_get_priority_max failed : %s", strerror(errno));
        return false;
    }

    if( schedPriority > maxAllowedPrio )
    {
        TDSCDMALogError("xp %d greater than max allowed for ttisched, %d", schedPriority, maxAllowedPrio);
        return false;
    }

    if( schedPriority < minAllowedPrio )
    {
        TDSCDMALogError("maxp %d lower than min allowed for ttisched, %d.", schedPriority, minAllowedPrio);
        return false;
    }

    if( pthread_attr_setschedpolicy(&attr,schedPolicy) )
    {
        TDSCDMALogError("pthread_attr_setschedpolicy failed: %s.", strerror(errno));
        return false;
    }

    // Get the scheduling-parameters portion of the attr structure initialized
    // via pthread_attr_init() above
    if( pthread_attr_getschedparam(&attr, &sched) )
    {
        TDSCDMALogError("pthread_attr_getschedparam failed : %s.", strerror(errno));
        return false;
    }
    // Update the priority with the value passed in
    sched.sched_priority = schedPriority;
    // Update the priority in the attr structure
    if( pthread_attr_setschedparam(&attr, &sched) )
    {
        TDSCDMALogError("pthread_attr_setschedparam failed : %s.", strerror(errno));
        return false;
    }

    if( pthread_attr_setscope(&attr, PTHREAD_SCOPE_SYSTEM) )
    {
        TDSCDMALogError("pthread_attr_setscope failed : %s", strerror(errno));
        return false;
    }

    TDSCDMALogNotice("begin to create tdscdma_udp_task_thread.", MODULE_TDSCDMA_CAP);
    if( pthread_create(&thread, &attr, tdscdma_udp_task_thread, 0) )
    {
        TDSCDMALogError("pthread_create tdscdmaUdptask thread failed: %s.", strerror(errno));
        return false;
    }
    
    return true;
}

